package com.qdlc.p2p.biz.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Splitter;
import com.qdlc.p2p.biz.borrowworker.BorrowHelper;
import com.qdlc.p2p.biz.borrowworker.worker.BorrowWorker;
import com.qdlc.p2p.biz.executer.AbstractExecuter;
import com.qdlc.p2p.biz.executer.ExecuterHelper;
import com.qdlc.p2p.biz.executer.impl.AutoBorrowTenderFreezeExecuter;
import com.qdlc.p2p.biz.executer.impl.BorrowExWaitInterestExecuter;
import com.qdlc.p2p.biz.executer.impl.ExperienceExecuter;
import com.qdlc.p2p.biz.executer.impl.UpRateCollectionExecuter;
import com.qdlc.p2p.biz.service.BorrowRepaymentService;
import com.qdlc.p2p.biz.service.BorrowTenderService;
import com.qdlc.p2p.biz.service.CollectPayService;
import com.qdlc.p2p.biz.service.TppInvestService;
import com.qdlc.p2p.biz.service.TppTradeService;
import com.qdlc.p2p.biz.task.ConcurrentUtil;
import com.qdlc.p2p.biz.task.impl.MailUtil;
import com.qdlc.p2p.biz.tpp.TppBaseInterface;
import com.qdlc.p2p.biz.tpp.TppServiceFactory;
import com.qdlc.p2p.biz.tpp.model.SinaModel;
import com.qdlc.p2p.common.constant.BorrowCategory;
import com.qdlc.p2p.common.constant.BorrowCollectionStatus;
import com.qdlc.p2p.common.constant.BorrowStatus;
import com.qdlc.p2p.common.constant.BorrowStyle;
import com.qdlc.p2p.common.constant.BorrowTenderStatus;
import com.qdlc.p2p.common.constant.BorrowTimeType;
import com.qdlc.p2p.common.constant.Global;
import com.qdlc.p2p.common.constant.LotteryCashType;
import com.qdlc.p2p.common.constant.RedEnvelopeType;
import com.qdlc.p2p.common.constant.RedUseType;
import com.qdlc.p2p.common.constant.SinaConstant;
import com.qdlc.p2p.common.constant.TradeCode;
import com.qdlc.p2p.common.core.ReturnResult;
import com.qdlc.p2p.common.exception.BorrowException;
import com.qdlc.p2p.common.exception.BusinessException;
import com.qdlc.p2p.common.util.BeanUtil;
import com.qdlc.p2p.common.util.BigDecimalUtil;
import com.qdlc.p2p.common.util.CollectionUtils;
import com.qdlc.p2p.common.util.DateUtil;
import com.qdlc.p2p.common.util.LogFactory;
import com.qdlc.p2p.common.util.MessageUtil;
import com.qdlc.p2p.common.util.NumberUtil;
import com.qdlc.p2p.common.util.StringUtil;
import com.qdlc.p2p.dal.common.SystemConfigHelper;
import com.qdlc.p2p.dal.common.SystemConfigHelper.Nid;
import com.qdlc.p2p.dal.dao.BondTenderDao;
import com.qdlc.p2p.dal.dao.BorrowCollectionDao;
import com.qdlc.p2p.dal.dao.BorrowDao;
import com.qdlc.p2p.dal.dao.BorrowTenderDao;
import com.qdlc.p2p.dal.dao.TppDao;
import com.qdlc.p2p.dal.dao.TppSinaSplitDao;
import com.qdlc.p2p.dal.dao.TppTradeLogDao;
import com.qdlc.p2p.dal.dao.UserAutoTenderLogDao;
import com.qdlc.p2p.dal.dao.UserVipUprateCollectionDao;
import com.qdlc.p2p.dal.dao.VerifyLogDao;
import com.qdlc.p2p.dal.dto.BondCollection;
import com.qdlc.p2p.dal.dto.BondTender;
import com.qdlc.p2p.dal.dto.Borrow;
import com.qdlc.p2p.dal.dto.BorrowCollection;
import com.qdlc.p2p.dal.dto.BorrowRepayment;
import com.qdlc.p2p.dal.dto.BorrowTender;
import com.qdlc.p2p.dal.dto.Tpp;
import com.qdlc.p2p.dal.dto.TppSinaSplit;
import com.qdlc.p2p.dal.dto.TppTradeLog;
import com.qdlc.p2p.dal.dto.User;
import com.qdlc.p2p.dal.dto.UserAutoTenderLog;
import com.qdlc.p2p.dal.dto.UserVipUprateCollection;
import com.qdlc.p2p.dal.dto.VerifyLog;
import com.qdlc.p2p.dal.model.BorrowModel;
import com.qdlc.p2p.dal.model.TppModel;
import com.qdlc.p2p.dal.model.TppTradeLogModel;
import com.qdlc.p2p.dal.model.UserAutoTenderLogModel;
import com.qdlc.p2p.dal.model.interest.EachPlan;
import com.qdlc.p2p.dal.model.interest.InstallmentRepaymentCalculator;
import com.qdlc.p2p.dal.model.interest.InterestCalculator;
import com.qdlc.p2p.dal.model.interest.MonthlyInterestCalculator;
import com.qdlc.p2p.dal.model.interest.OnetimeRepaymentCalculator;
import com.qdlc.p2p.dal.util.UserUtils;

/**
 * 第三方投资业务处理
 *
 * @author wuaj
 * @version 1.1.0.0
 */
@Service("tppInvestService")
public class TppInvestServiceImpl implements TppInvestService {

    private static Logger logger = Logger.getLogger(TppInvestServiceImpl.class);

    private static Logger tradeLogger = LogFactory.TRADE_LOGGER;

    @Resource
    private BorrowTenderDao borrowTenderDao;

    @Resource
    private BorrowDao borrowDao;

    @Resource
    private TppDao tppDao;

    @Resource
    private BorrowCollectionDao borrowCollectionDao;

    @Resource
    private BorrowTenderService borrowTenderService;

    @Resource
    private UserAutoTenderLogDao userAutoTenderLogDao;

    @Resource
    private UserVipUprateCollectionDao userVipUprateCollectionDao;

    @Resource
    private BondTenderDao bondTenderDao;

    @Resource
    private TppTradeLogDao tppTradeLogDao;

    @Resource
    private TppTradeService tppTradeService;

    @Resource
    private TppSinaSplitDao tppSinaSplitDao;

    @Resource
    private BorrowTenderDao tenderDao;

    @Resource
    private VerifyLogDao verifyLogDao;

    @Resource
    private BorrowRepaymentService borrowRepaymentService;

    @Resource
    @Qualifier("borrowRepayPayService")
    private CollectPayService borrowRepayPayService;

    @Resource
    @Qualifier("borrowRepayUpRatePayService")
    private CollectPayService borrowRepayUpRatePayService;

    @Resource
    @Qualifier("borrowRepayUpRateCollectService")
    private CollectPayService borrowRepayUpRateCollectService;

    @Resource
    @Qualifier("redEnvelopeCollectService")
    private CollectPayService redEnvelopeCollectService;

    @Resource
    @Qualifier("redEnvelopePayService")
    private CollectPayService redEnvelopePayService;

    @Resource
    @Qualifier("lotteryCollectService")
    private CollectPayService lotteryCollectService;

    @Resource
    @Qualifier("lotteryPayService")
    private CollectPayService lotteryPayService;

    /**
     * 第三方托管接口
     */
    TppBaseInterface tppService = TppServiceFactory.newIntance();

   /* @Override
    public void addTender(BorrowModel borrowModel) {

        // 标
        Borrow borrow = borrowDao.find(borrowModel.getId());

        // 生成订单号
        String orderNo = borrowModel.getTenderBilNo();

        // 投标时间
        Date tenderTime = DateUtil.getNow();

        // 投标金额
        double tenderAccount = borrowModel.getMoney();

        // 投标用户
        User tenderUser = borrowModel.getUser();

        // 体验标单独处理
        if (borrowModel.getCategory() == BorrowCategory.EXPERIENCE) {

            logger.info(MessageFormat.format("体验金投标标ID:{0} 体验券金额:{1} 体验券ID:{2}", borrowModel.getId(), tenderAccount, borrowModel.getExperiences()[0]));

            // 计算利息
            InterestCalculator ic = experienceInterestCalculator(borrowModel, tenderTime);

            // 生成投标记录
            BorrowTender borrowTender = saveBorrowTender(borrowModel, borrow, ic, BorrowTenderType.FROM_SITE);

            // 冻结投资人本金
            Global.setTransfer("borrow", borrowModel);
            Global.setTransfer("money", tenderAccount);
            Global.setTransfer("user", tenderUser);

            //Global.setTransfer("tenderAccount", borrowTender.getAccount());
            //Global.setTransfer("tender", borrowTender);
            //Global.setTransfer("experienceMoney", totalExperienceMoney);
            // 投资人投资冻结资金
            AbstractExecuter borrowExperienceTenderExcuter = ExecuterHelper.doExecuter("borrowExperienceTenderExcuter");
            borrowExperienceTenderExcuter.execute(tenderAccount, tenderUser, new User(1));

            // 处理体验券
            Global.setTransfer("experiences", borrowModel.getExperiences());
            Global.setTransfer("tender", borrowTender);
            AbstractExecuter experienceTenderExecuter = ExecuterHelper.doExecuter("experienceTenderExecuter");
            experienceTenderExecuter.execute(borrowTender.getAccount(), tenderUser);

            double tenderTotalAccount = borrowModel.getAccount();  // 标总金额
            double accountYes = borrowModel.getAccountYes(); // 已投金额

            // 更新已投金额 (已投金额 + 投标金额)
            accountYes = BigDecimalUtil.add(accountYes, tenderAccount);
            double scales = BigDecimalUtil.round(BigDecimalUtil.div(accountYes, tenderTotalAccount) * 100);
            // 由于四舍五入导致99.999999的数据会变成100而无法投资，所以变为99.99
            if (scales == 100 && tenderTotalAccount != accountYes) {
                scales = 99.99;
            }

            // 更新投标金额 投标次数作为更新条件 保存投标的原子性 (满标自动下架)
            borrow = borrowDao.tenderUpdate(borrowModel.getId(), tenderAccount, scales, borrowModel.getStatus(), borrowModel.getTenderTimes(), true);

            // 放款记录生成
            experienceCreateCollectionList(borrowTender, ic, borrow);

            // 生成待收利息
            double interest = borrowTender.getInterest(); // 利息
            Global.setTransfer("money", interest);
            Global.setTransfer("tender", borrowTender);
            AbstractExecuter waitExecuter = ExecuterHelper.doExecuter("borrowExWaitInterestExecuter");
            waitExecuter.execute(interest, tenderUser, new User(1));

            // 非体验标
        } else {
            // 投标使用红包总额
            double totalRedEnvelopeMoney = borrowModel.getTotalRedEnvelopeMoney();

            // 生成投标记录 利息在复审时计算
            saveBorrowTender(borrowModel, borrow, null, BorrowTenderType.FROM_SITE);

            // 保存投标提交的其余扩展参数
            TppTenderLog tppTenderLog = new TppTenderLog();
            tppTenderLog.setBorrowId(borrowModel.getId());
            tppTenderLog.setOrderNo(orderNo);
            tppTenderLog.setParam(borrowModel.getParam());
            tppTenderLog.setAddTime(tenderTime);
            tppTenderLogDao.save(tppTenderLog);

            // 投标用户标识
            String tppUserCustId = tenderUser.getTppUserCustId();

            TppTradeLog tppTradeLog = TppTradeLogBuilder.newBuilderForTradeCode1001()
                    .setOrderNo(orderNo) // 订单号
                    .setTppUserCustId(tppUserCustId) // 投标用户标识
                    .setToTppUserCustId(borrow.getUser().getTppUserCustId()) // 标所属用户标识
                    .setBorrowId(borrowModel.getId()) // 标ID
                    .setMoney(tenderAccount) // 投标金额
                    .setAddTime(tenderTime) // 投标时间
                    .setAmount(0)
                    .setSummary(SummaryConstant.TRADE_SERVICE_TENDER)
                    .setIdentityType(IdentityType.UID)
                    .setBorrowRepaymentId(0)
                    .setSplitList("")
                    .build();
            tppTradeLogDao.save(tppTradeLog);

            //调用代收接口
            HostingCollectTradeParam bizParam = HostingCollectTradeParam.build()
                    .setIdentityId(tppUserCustId)
                    .setAmount(tenderAccount)
                    .setGoodsId(String.valueOf(borrowModel.getId()))
                    .setSummary(SummaryConstant.TRADE_SERVICE_TENDER.getSummaryName())
                    .setCanRepayOnFailed("N")
                    .setOutOrderNo(orderNo)
                    .setIdentityType(IdentityType.UID)
                    .setAccountType(AccountType.SAVING_POT)
                    .setNofifyUrl(notifyUrl);
            CreateHostingCollectTradeResponse response = sinaPayService.createHostingCollectTrade(bizParam);

            // 投标成功
            if (response.success()) {
                double tenderTotalAccount = borrowModel.getAccount();  // 标总金额
                double accountYes = borrowModel.getAccountYes(); // 已投金额

                // 更新已投金额 (已投金额 + 投标金额)
                accountYes = BigDecimalUtil.add(accountYes, tenderAccount);
                double scales = BigDecimalUtil.round(BigDecimalUtil.div(accountYes, tenderTotalAccount) * 100);
                // 由于四舍五入导致99.999999的数据会变成100而无法投资，所以变为99.99
                if (scales == 100 && tenderTotalAccount != accountYes) {
                    scales = 99.99;
                }

                // 更新投标金额 投标次数作为更新条件 保存投标的原子性 (满标自动下架)
                borrow = borrowDao.tenderUpdate(borrowModel.getId(), tenderAccount, scales, borrowModel.getStatus(), borrowModel.getTenderTimes(), false);

                // 冻结投标金额
                accountDao.modify(0, -tenderAccount, tenderAccount, tenderUser.getUserId());

                try {
                    // 赠送活动：投趣影标赠送电影票
                    if (borrow.getType() == BorrowType.TYPE_MORTGAGE)
                        NewActivityAwardExecutor.giveByTache(borrowModel.getUser(), EnumActicityPlanNid.TENDER.getValue());
                } catch (Exception e) {
                    // 人品差
                    e.printStackTrace();
                }
                // 使用红包的场合，红包兑现(每次投标只能使用一个红包且只能是虚拟红包，否则不兑换)
                try {
                    if (totalRedEnvelopeMoney > 0 && borrowModel.getRedEnvelopeIds().length < 2) {
                        userRedEnvelopeService.redEnvelopeExchangeForTender(borrowModel.getRedEnvelopeIds(), borrowModel.getUser());// 区分来源为投标
                    } else {
                        throw new BorrowException("多个红包,无法兑换!");
                    }
                } catch (Exception e) {
                    // 人品差
                    e.printStackTrace();
                }
            } else {
                throw new BorrowException(MessageFormat.format("投标失败!reqStatus:{0} reqErrorMessage:{1} resCode:{2} resMessage:{3}",
                        response.getReqStatus(), response.getReqErrorMessage(), response.getResponseCode(), response.getResponseMessage()));
            }
        }
    }*/

    @Override
    public void addTppTender(BorrowModel model) {
        BorrowTender borrowTender = borrowTenderDao.getTenderByBillNo(model.getTenderBilNo());
        if (borrowTender != null && borrowTender.getStatus() == BorrowTenderStatus.TREAT) {
            Borrow borrow = borrowDao.find(model.getId());
            User user = UserUtils.getUserByTppCustId(model.getTppUserCustId());
            model.setUser(user);

            // 平台投标业务处理
            BorrowTender tender = borrowTenderService.addTender(borrow, model);

            // 投标订单日期
            tender.setTenderBilDate(model.getTenderBilDate());

            borrowTenderDao.update(tender);

            // 需要取borrow最新状况，所有需要重新查询一遍
            Borrow b = borrowDao.find(borrow.getId());
            double tenderTotal = borrowTenderDao.getBorrowTenderSum(b.getId(), BorrowTenderStatus.PROCESSED);
            //如果投标 已处理的金额  等于 借款标发标金额，那么可以自动满审/还款
            if (tenderTotal == b.getAccount()) {
                BorrowWorker worker = BorrowHelper.getWorker(b);
                worker.immediateRepayAfterTender(tender);
            }
        }
    }

    @Override
    public void quartzAddTppTender() {

        // 投标代收后异常列表
        long begin = System.currentTimeMillis();
        List<BorrowTender> tenderList = tenderDao.findByProperty("status", 0);// 投标待处理
        for (BorrowTender borrowTender : tenderList) {

            String tradeNo = borrowTender.getTenderBilNo();// 订单号
            // 新浪调用Log都会生成
            TppTradeLog tppTradeLog = tppTradeService.find(tradeNo);
            // 异步回调 订单状态为成功情况
            if (tppTradeLog == null) {
                logger.info("投标代收后调度任务-代收订单号：" + tradeNo + "不存在！");
                continue;
            }
            if (SinaConstant.TRADE_STATUS_PAY_FINISHED.equals(tppTradeLog.getTradeStatus())) {// 交易状态 - 已付款
                try {
                    logger.info("投标代收后调度任务-代收投资金(1001)业务重新处理(代收回调后) START 订单号[" + tradeNo + "]");
                    BorrowModel bm = new BorrowModel();
                    long borrowId = tppTradeLog.getBorrowId();
                    String tppUserCustId = tppTradeLog.getTppUserCustId();
                    bm.setId(borrowId);
                    bm.setBidNo(tppTradeLog.getOrderNo());
                    bm.setTenderBilNo(tppTradeLog.getOrderNo());
                    bm.setTenderBilDate(DateUtil.dateStr3(tppTradeLog.getTradeTime()));
                    // borrowTender的account金额包含现金、红包、体验券
                    bm.setMoney(tppTradeLog.getAmount());
                    bm.setTppUserCustId(tppUserCustId);
                    JSONObject merPivJson = JSON.parseObject(tppTradeLog.getMemo());
                    if (merPivJson != null) {
                        long rateInterestId = NumberUtil.getLong(merPivJson.getString("rateId"));
                        String redEnvelopeStr = merPivJson.getString("redStr");
                        double redEnvelopeMoney = merPivJson.getDoubleValue("redMoney");
                        String experStr = merPivJson.getString("experStr");
                        double experienceMoney = merPivJson.getDoubleValue("experMoney");
                        long userId = NumberUtil.getLong(merPivJson.getString("userId"));
                        bm.setUserId(userId);
                        bm.setRateInterestId(rateInterestId);
                        bm.setRedEnvelopeStr(redEnvelopeStr);
                        bm.setTotalRedEnvelopeMoney(redEnvelopeMoney);
                        bm.setExperiences((long[]) ConvertUtils.convert(experStr.split(","), long.class));
                        bm.setTotalExperienceMoney(experienceMoney);
                    }
                    this.addTppTender(bm);// 重新处理业务
                } catch (Exception e) {
                    logger.error(e + "投标代收后调度任务-代收投资金(1001)业务重新处理(代收回调后) 出错 订单号[" + tradeNo + "]");
                    MailUtil.sendMail("投标代收后调度任务-代收投资金(1001)业务重新处理(代收回调后) 出错 订单号[" + tradeNo + "]", e);
                    continue;
                }
            }
        }
        long end = System.currentTimeMillis();
        logger.info("投标代收后调度JOB 结束，用户数：[" + tenderList.size() + "]人," + "共耗时：[" + (end - begin) / 1000 + "]秒");
    }

    @Override
    public void tppAutoTender(double money, double autoTenderMaxAcount, Borrow borrow, User user) {

//		String ordId = OrderNoUtil.getInstance().getSerialNumber();
        BorrowModel model = new BorrowModel();
        model.setId(borrow.getId());
//		model.setTenderBilNo(ordId);
        model.setMoney(money);
        model.setTenderBilDate(DateUtil.dateStr3(DateUtil.getNow()));
        model.setAddIp(Global.getIP());
        model.setUser(user);
        model.setTotalExperienceMoney(0);

        borrow = borrowDao.find(model.getId());
        double accountYes = BigDecimalUtil.add(money, borrow.getAccountYes());//剩余金额
        if (accountYes <= borrow.getAccount()) { //校验并发
           /* BorrowTender tender = fillTender(model, Byte.parseByte("1"), borrow);
            if (tender.getAccount() > 0) { //去掉并发
                String ordId = OrderNoUtil.getInstance().getSerialNumber();
                model.setTenderBilNo(ordId);
                tender.setTenderBilNo(ordId);
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("type", SinaConstant.TRADE_SERVICE_AUTO_TENDER);
                map.put("tenderMoney", money);
                map.put("borrowId", borrow.getId());
                map.put("userId", user.getUserId());
                map.put("tppUserCustId", user.getTppUserCustId());
                //插入交易记录
                TppTradeLog tppTradeLog = new TppTradeLog(user.getTppUserCustId(), borrow.getUser().getTppUserCustId(), SinaConstant.IDENTITY_TYPE_UID, money, 0, ordId,
                        SinaConstant.TRADE_STATUS_WAIT_PAY, SinaConstant.TRADE_CODE_1001,
                        SinaConstant.TRADE_SERVICE_AUTO_TENDER, borrow.getId(), 0, "", JSON.toJSONString(map));
                SinaCollectTrade collTrade = (SinaCollectTrade) tppTradeService.collTrade(tppTradeLog);
                if (collTrade != null && SinaConstant.TRADE_STATUS_PAY_FINISHED.equals(collTrade.getTrade_status())) {
                    saveTender(tender, model);
                }
            }*/
        } else {
            throw new BorrowException("投标失败！此标可能已满！", 1);
        }
    }

    /**
     * @param tender
     * @param model
     * @param
     */
    private void saveTender(BorrowTender tender, BorrowModel model) {
        /*Borrow borrow = borrowDao.find(model.getId());
        borrowTenderDao.save(tender);
        double accountYes = BigDecimalUtil.add(borrow.getAccountYes(), tender.getAccount());
        double scales = BigDecimalUtil.round(BigDecimalUtil.div(accountYes, borrow.getAccount()) * 100);
        // 由于四舍五入导致99.999999的数据会变成100而无法投资，所以变为99.99
        if (scales == 100 && borrow.getAccount() != accountYes) {
            scales = 99.99;
        }
        borrowDao.update(tender.getAccount(), scales, borrow.getStatus(), borrow.getId());*/
    }

    /**
     * 自动投标核心业务处理
     *
     * @param borrowModel           投标金额
     */
    @Override
    public void autoTenderHander(BorrowModel borrowModel) {
        Borrow borrow = borrowDao.find(borrowModel.getId());
        User user = UserUtils.getUserByTppCustId(borrowModel.getTppUserCustId());
        double money = borrowModel.getMoney();
        String ordId = borrowModel.getTenderBilNo();
        BorrowTender borrowTender = borrowTenderDao.getTenderByBillNo(ordId);
        if (borrowTender != null && borrowTender.getStatus() == BorrowTenderStatus.TREAT) {
            //String ordDate = DateUtil.dateStr3(DateUtil.getNow());
            UserAutoTenderLog userAutoTenderLog = new UserAutoTenderLog();
            userAutoTenderLog.setUser(user);
            userAutoTenderLog.setBorrow(borrow);
            userAutoTenderLog.setAddTime(DateUtil.getNow());
            //如果已借金额大于自动投标最大额度，那么直接终止
            //double accountYes = borrow.getAccountYes();
            //剩余可投
            //double borrowAccountYes =  BigDecimalUtil.add(money,accountYes);

            Global.setTransfer("borrow", borrow);
            Global.setTransfer("money", money);
            Global.setTransfer("user", user);
            Global.setTransfer("noticeTime", DateUtil.getNow());
            Global.setTransfer("redEnvelopeMoney", 0);
            Global.setTransfer("experienceMoney", 0);
            //自动投标本地冻结相关处理
            AbstractExecuter borrowTenderExecuter = ExecuterHelper.getExecuter(AutoBorrowTenderFreezeExecuter.class);
            borrowTenderExecuter.execute(money, user, borrow.getUser());
            //更改标相关
            //borrowDao.update(money, BigDecimalUtil.div(borrowAccountYes, borrow.getAccount()) * 100, borrow.getStatus(), borrow.getId());

				/*BorrowTender tender = new BorrowTender();
                tender.setBorrow(borrow);
				tender.setMoney(money);
				tender.setAccount(money);
				tender.setRealAmount(money);
				tender.setStatus(0);
				tender.setAddTime(DateUtil.getNow());
				tender.setAddIp(Global.getIP());
				tender.setUser(user);
				tender.setTenderType(Byte.parseByte("1"));
				// 投标订单号
				tender.setTenderBilNo(ordId);
				// 投标订单日期
				tender.setTenderBilDate(ordDate);*/
            // 投标冻结单号
                /*tender.setTrxId(trxId);*/
            //投标记录
            //tender = borrowTenderDao.addBorrowTender(tender);
            //用于标记是投标的情况,BorrowHelper.getWorker()需要使用,若不设置，利息计算器将会出错
            borrow.setIsTender(1);
            double validAccount = borrowTender.getAccount();
            BorrowWorker worker = BorrowHelper.getWorker(borrow);
            InterestCalculator ic = worker.interestCalculator(validAccount);
            borrowTender = worker.tenderSuccess(borrowTender, ic);
                /*List<BorrowCollection> collectList = worker.createCollectionList(borrowTender, ic);
                //待收记录
				borrowCollectionDao.save(collectList);*/

            userAutoTenderLog.setTenderMoney(money);
            userAutoTenderLog.setStatus(UserAutoTenderLogModel.TENDER_SUCCESS);
            userAutoTenderLog.setRemark(MessageUtil.getMessage("MF105001012"));
            userAutoTenderLogDao.save(userAutoTenderLog);
        }
    }

    @Override
    public void doTppRepay(List<BorrowCollection> borrowCollectionList, List<BondCollection> bondCollectionList) {
        // 第三方处理任务列表
        List<TppModel> taskList = new ArrayList<TppModel>();
        for (BorrowCollection collection : borrowCollectionList) {
            User toUser = collection.getUser();
            //BorrowTender tender = collection.getTender();
            String tppUserCustId = UserUtils.getUserTppCustId(toUser.getUserId());
            Map<String, Object> map = new HashMap<String, Object>();
            double total = 0.0;

            // 体验券本金
            ExperienceExecuter experienceExecuter = ExecuterHelper.getExecuter(ExperienceExecuter.class);
            double experienceCapital = experienceExecuter.sumCollectionExperienceCapital(collection.getId());

            // 借款标还款金额 = 应收款本金 - 债权转让本金 - 体验券本金
            //double money = BigDecimalUtil.add(collection.getCapital(), -collection.getBondCapital(), -experienceCapital);
            // 实收现金 然后把体验金跟管理费 分帐分掉 上面应该是个bug
            double money = BigDecimalUtil.add(collection.getCapital());

            // 借款标还款利息 = （应收款利息 - 债权转让利息）
            double interest = BigDecimalUtil.add(collection.getInterest(), -collection.getBondInterest());
            //利息管理费
            double interestFee = 0.0;
            if (interest > 0) {
                double borrow_fee = SystemConfigHelper.getDoubleValue(Nid.INVESTOR_MANAGE_FEE);
                interestFee = BigDecimalUtil.mul(interest, borrow_fee);
                interestFee = BigDecimalUtil.round(interestFee);
            }

            // 逾期利息发放
            double lateInterest = collection.getLateInterest();

            // VIP利息发放
            UserVipUprateCollection vipUprateColl = userVipUprateCollectionDao.getUserVipUprateCollByCollId(collection.getId());
            double vipInterest = 0.0;
            if (vipUprateColl != null) {
                vipInterest = vipUprateColl.getRepayInterest();
            }

            // 获取加息利息
            UpRateCollectionExecuter upRateInterestExecuter = ExecuterHelper.getExecuter(UpRateCollectionExecuter.class);
            double upRateInterest = upRateInterestExecuter.getUpRateInterestByCollectionId(collection.getId());

            total = BigDecimalUtil.add(money, interest, lateInterest, vipInterest, upRateInterest);

            Tpp tpp = new Tpp(TppModel.DOREPAY, TppModel.TPP_REPAY, collection.getBorrow().getUser(), toUser, total, null);
            TppModel tppModel = TppModel.instance(tpp);
            tppModel.setSubOrdId(tppModel.getOrderId());
            tppModel.setOut_trade_code(SinaConstant.TRADE_CODE_2002); // 还款
            tppModel.setTppBorrowId(collection.getBorrow().getId() + "");
            tppModel.setSummary("还款");

            map.put("collectionId", collection.getId());
            map.put("experienceCapital", experienceCapital);
            map.put("tenderMoney", money);
            map.put("interest", interest);
            map.put("lateInterest", lateInterest);
            map.put("vipInterest", vipInterest);
            map.put("upRateInterest", upRateInterest);
            map.put("interestFee", interestFee);
            List<TppSinaSplit> splitList = new ArrayList<TppSinaSplit>();
            String memberEmail = SystemConfigHelper.getValue(Nid.MEMBER_EMAIL);
            String accountType = SystemConfigHelper.getValue(Nid.ACCOUNT_TYPE);
            if (interestFee > 0) {
                TppSinaSplit split = new TppSinaSplit(tppModel.getOrderId(), tppUserCustId, SinaConstant.IDENTITY_TYPE_UID, accountType,
                        memberEmail, SinaConstant.IDENTITY_TYPE_EMAIL, accountType, interestFee + "", "利息管理费");
                splitList.add(split);
            }

            if (experienceCapital > 0) {
                TppSinaSplit split = new TppSinaSplit(tppModel.getOrderId(), tppUserCustId, SinaConstant.IDENTITY_TYPE_UID, accountType,
                        memberEmail, SinaConstant.IDENTITY_TYPE_EMAIL, accountType, experienceCapital + "", "体验券返还平台");
                splitList.add(split);
            }
            tppSinaSplitDao.save(splitList);

            tppModel.setSplit_list(splitList);
            taskList.add(tppModel);
            String borrowTppUserCustId = UserUtils.getUserTppCustId(collection.getBorrow().getUser().getUserId());
            TppTradeLog tppTradeLog = new TppTradeLog(borrowTppUserCustId, tppUserCustId, SinaConstant.IDENTITY_TYPE_UID, total, 0, tppModel.getOrderId(),
                    SinaConstant.TRADE_STATUS_WAIT_PAY, SinaConstant.TRADE_CODE_2002,
                    SinaConstant.TRADE_SERVICE_REPAY, collection.getBorrow().getId(), 0, "", JSON.toJSONString(map));
            tppTradeLog.setAddTime(DateUtil.getNow());
            tppTradeLogDao.save(tppTradeLog);

        }

        // 债权待收
        for (BondCollection bondCollection : bondCollectionList) {
            double manageFee = BigDecimalUtil.mul(BigDecimalUtil.sub(bondCollection.getInterest(), bondCollection.getBondInterest()), SystemConfigHelper.getDoubleValue(Nid.INVESTOR_MANAGE_FEE));
            double money = BigDecimalUtil.add(bondCollection.getCapital(), -bondCollection.getBondCapital(), bondCollection.getInterest(), -bondCollection.getBondInterest(), bondCollection.getLateInterest());
            BorrowTender borrowTender = borrowTenderDao.find(bondCollection.getBorrowTenderId());
            BondTender bondTender = bondTenderDao.getBondTenderById(bondCollection.getBondTenderId());
            Tpp tpp = new Tpp(TppModel.DOREPAY, TppModel.TPP_REPAY, bondCollection.getBorrow().getUser(), bondCollection.getUser(), money, borrowTender);
            tpp.setServFee(manageFee);
            tpp.setSubOrdId(bondTender.getOrderId());
            tpp.setSubOrdDate(bondTender.getOrderDate());
            taskList.add(TppModel.instance(tpp));
        }

        // 执行队列
        ConcurrentUtil.tppTask(taskList);
    }

    @Override
    public void doTppWebAdvance(List<BorrowCollection> list) {
        // 第三方处理任务列表
        List<TppModel> taskList = new ArrayList<TppModel>();
        for (BorrowCollection borrowCollection : list) {
            // 体验券本金
        	ExperienceExecuter experienceExecuter = ExecuterHelper.getExecuter(ExperienceExecuter.class);
            double experienceCapital = experienceExecuter.sumCollectionExperienceCapital(borrowCollection.getId());

            // 归还投资人本金 = 待收本金 - 债权转出本金 - 体验券本金
            double capital = BigDecimalUtil.add(borrowCollection.getCapital(), -borrowCollection.getBondCapital(), -experienceCapital);
            // 归还投资人利息 = 待收利息 - 债权转出利息
            double conllectionInterest = BigDecimalUtil.sub(borrowCollection.getInterest(), borrowCollection.getBondInterest());

            User toUser = borrowCollection.getUser();
            BorrowTender tender = borrowCollection.getTender();

            // 归还投资人本金
            if (capital > 0) {
                Tpp tpp = new Tpp(TppModel.ADVANCEREPAY, TppModel.TPP_TRANSFER, null, toUser, capital, tender);
                taskList.add(TppModel.instance(tpp));
            }

            // 归还投资人利息
            if (conllectionInterest > 0) {
                // 平台转账给用户只需要转扣除利息管理费利息
                double manageFee = BigDecimalUtil.round(BigDecimalUtil.mul(conllectionInterest, SystemConfigHelper.getDoubleValue(Nid.INVESTOR_MANAGE_FEE)));
                conllectionInterest = BigDecimalUtil.sub(conllectionInterest, manageFee);
                Tpp tpp = new Tpp(TppModel.ADVANCEREPAY, TppModel.TPP_TRANSFER, null, toUser, conllectionInterest, tender);
                taskList.add(TppModel.instance(tpp));
            }

            // 归还投资人逾期利息
            if (borrowCollection.getLateInterest() > 0) {
                Tpp tpp = new Tpp(TppModel.ADVANCEREPAY, TppModel.TPP_TRANSFER, null, toUser, borrowCollection.getLateInterest(), tender);
                taskList.add(TppModel.instance(tpp));
            }

            // 归还投资人加息利息
            UpRateCollectionExecuter upRateInterestExecuter = ExecuterHelper.getExecuter(UpRateCollectionExecuter.class);
            double upRateInterest = upRateInterestExecuter.getUpRateInterestByCollectionId(borrowCollection.getId());
            if (upRateInterest > 0) {
                Tpp tpp = new Tpp(TppModel.ADVANCEREPAY, TppModel.TPP_TRANSFER, null, toUser, upRateInterest, tender);
                taskList.add(TppModel.instance(tpp));
            }

            // 归还投资人VIP加息利息
            UserVipUprateCollection vipUprateColl = userVipUprateCollectionDao.getUserVipUprateCollByCollId(borrowCollection.getId());
            if (vipUprateColl != null) {
                double vipInterest = vipUprateColl.getRepayInterest();
                Tpp tpp = new Tpp(TppModel.DOREPAY, TppModel.TPP_TRANSFER, null, toUser, vipInterest, tender);
                taskList.add(TppModel.instance(tpp));
            }
        }

        // 执行队列
        ConcurrentUtil.tppTask(taskList);
    }

    @Override
    public void doTppLateRepayment(BorrowRepayment borrowRepayment) {
        // 处理第三方业务
        List<TppModel> taskList = new ArrayList<TppModel>();
        User user = borrowRepayment.getUser();
        Borrow borrow = borrowRepayment.getBorrow();
        // 投资人收款列表
        List<BorrowCollection> list = borrowCollectionDao.list(borrow.getId(), borrowRepayment.getPeriod(), 1);
        for (BorrowCollection borrowCollection : list) {
            BorrowTender tender = borrowCollection.getTender();
            // 逾期利息
            double lateInterest = BigDecimalUtil.mul(borrowRepayment.getLateInterest(), (BigDecimalUtil.div(borrowCollection.getInterest(), borrowRepayment.getInterest())));
            // 还款金额 = 应还款金额 + 逾期利息
            double transAmount = BigDecimalUtil.add(borrowCollection.getCapital(), borrowCollection.getInterest(), lateInterest);
            Tpp tpp = new Tpp(TppModel.DOREPAY, TppModel.TPP_REPAY, user, null, transAmount, tender);
            tpp.setSubOrdId(tender.getTenderBilNo());
            tpp.setSubOrdDate(tender.getTenderBilDate());
            tpp.setToTppUserCustId(SystemConfigHelper.getValue(Nid.MERCHANT_ID));
            taskList.add(TppModel.instance(tpp));
        }
        ConcurrentUtil.tppTask(taskList);
    }

    /**
     * 投标放款业务
     *
     * @param tppModel
     * @return
     */
    public Object doTenderLoan(TppModel tppModel) {
        return tppService.tppLoan(tppModel);
    }

    /**
     * 解冻业务
     *
     * @param tppModel
     */
    public Object doUnfreeze(TppModel tppModel) {
        return tppService.tppUnFreeze(tppModel);
    }

    /**
     * 还款业务
     *
     * @param tppModel
     */
    public Object doBorrowRepayment(TppModel tppModel) {
        return tppService.tppRepayment(tppModel);
    }

    /**
     * 转账业务
     *
     * @param tppModel
     */
    public Object doTransfer(TppModel tppModel) {
        return tppService.tppTransfer(tppModel);
    }

    /**
     * 退款业务
     *
     * @param tppModel
     */
    public Object doRefund(TppModel tppModel) {
        return tppService.tppRefund(tppModel);
    }

    @Override
    public void doTppTask(List<TppModel> taskList) {
        if (CollectionUtils.isNotNullOrEmpty(taskList)) {
            boolean isSuccess = true;
            SinaModel sinaModel = null;
            String desc = "";

            for (TppModel tppModel : taskList) {
                if (null == tppModel) {
                    continue;
                }

                if (isSuccess) {
                    try {
                        String tppType = tppModel.getTppType();

                        // 放款
                        if (TppModel.TPP_LOAN.equals(tppType)) {
                            desc = "代付";
                            sinaModel = (SinaModel) doTenderLoan(tppModel);
                            // 还款
                        } else if (TppModel.TPP_REPAY.equals(tppType)) {
                            desc = "代付";
                            sinaModel = (SinaModel) doBorrowRepayment(tppModel);
                            // 转账
                        } else if (TppModel.TPP_TRANSFER.equals(tppType)) {
                            desc = "转账";
                            sinaModel = (SinaModel) doTransfer(tppModel);
                            // 解冻
                        } else if (TppModel.TPP_UNFREEZE.equals(tppType)) {
                            desc = "解冻";
                            sinaModel = (SinaModel) doUnfreeze(tppModel);
                            // 退款
                        } else if (TppModel.TPP_REFUND.equals(tppType)) {
                            desc = "退款";
                            sinaModel = (SinaModel) doRefund(tppModel);
                        }
                        if (null == sinaModel) {
                            isSuccess = false;
                            tppModel.setStatus(TppModel.STATUS_FAIL);
                            tppModel.setRespDesc(desc + "处理失败");
                        } else {
                            tppModel.setStatus(TppModel.STATUS_SUCEESS);
                            tppModel.setRespDesc(desc + "处理成功");
                        }
                    } catch (Exception e) {
                        isSuccess = false;
                        tppModel.setStatus(TppModel.STATUS_FAIL);
                        tppModel.setRespDesc(e.getMessage());
                        tradeLogger.error("第三方业务处理异常！", e);
                    }
                }

                try {
                    // 更新操作日志
                    tppDao.save(tppModel.prototype());
                } catch (Exception e) {
                    tradeLogger.error("保存交易信息异常！", e);
                }
            }
        }
    }

    @Override
    public void tppDispatchTask(List<TppModel> taskList) {
        boolean isSuccess = true;
        String desc = "";
        int autoDispatch = TppTradeLogModel.IS_AUTO;// 自动调度标识 1:自动，0:非自动
        for (TppModel tppModel : taskList) {
        	long id = tppModel.getId();
        	Tpp tpp = tppDao.find(id);
            if (isSuccess && !StringUtil.isBlank(tpp) && tpp.getStatus() != TppModel.STATUS_SUCEESS) {// 防止重复处理
            	// 先更新调度状态，防止脏数据
            	tppDao.updateStatus(id, TppModel.STATUS_SUCEESS);
                try {
                	// 红包兑现
                    if (TppModel.RED_ENVELOPE_EXCHANGE.equals(tppModel.getServiceType())) {
                    	TradeCode tradeCode = TradeCode.getTradeCodeByType(tppModel.getTradeType());// 交易类型
                    	// 代收红包
                    	if (TradeCode.C1003.equals(tradeCode)) {
                			String redType = tppModel.getFlag();// 红包类型
                			long exchangeUserId = tppModel.getToUser().getUserId();// 收款用户ID
                			// 红包IDS
            		        List<String> redIdList = Splitter.on(",").omitEmptyStrings().splitToList(tppModel.getExtended());
            		        int size = redIdList == null ? 0 : redIdList.size();
            		        long[] redEnvelopeIds = new long[size];
            		        if (size > 0) {
            		            for (int i = 0; i < size; i++) {
            		            	redEnvelopeIds[i] = Long.valueOf(redIdList.get(i));
            		            }
                                if (redType.equals(RedEnvelopeType.CASH + "")) {// 现金红包
                                    redEnvelopeExchange(redEnvelopeIds, exchangeUserId, RedEnvelopeType.CASH, RedUseType.EXCHANGE_AMOUNT, autoDispatch);
                                } else if (redType.equals(RedEnvelopeType.VIRTUAL + "")) {
                                    redEnvelopeExchange(redEnvelopeIds, exchangeUserId, RedEnvelopeType.VIRTUAL, RedUseType.EXCHANGE_AMOUNT, autoDispatch);
                                }
                            } else {
            		        	desc = "→没有可兑现红包";
            		        }

            			// 代付红包
                		} else if (TradeCode.C2003.equals(tradeCode)) {
                			// 根据订单号 查询代收Log
                	        TppTradeLog tppTradeLog = tppTradeLogDao.find(tppModel.getOrderId());
                	        tppTradeLog.setAutoDispatch(autoDispatch);
                            try {
                                TppTradeLog newTppTradeLog = redEnvelopePayService.createOrder(tppTradeLog);
                                ReturnResult returnResult = redEnvelopePayService.requestOrder(newTppTradeLog);
                                if (returnResult.isError()) {
                                    // do nothing
                                    com.qdlc.p2p.common.util.MailUtil.sendMail("投标 - 兑现红包 - 代付提交成功 - 兑换失败", "红包兑现失败", returnResult.getErrorInfo());
                                }
                            } catch (Exception ex) {
                                com.qdlc.p2p.common.util.MailUtil.sendMail("投标 - 兑现红包 - 代付提交成功 - 兑换失败", "红包兑现失败", "");
                            }
                		}
                    }
                    //抽奖
                    else if(TppModel.SIGN_LOTTERY_MONEY.equals(tppModel.getServiceType())){
                        TradeCode tradeCode = TradeCode.getTradeCodeByType(tppModel.getTradeType());// 交易类型
                        if (TradeCode.C1006.equals(tradeCode)) {
                            String lotteryType  = tppModel.getFlag();// 抽奖类型
                            long toUserId = tppModel.getToUser().getUserId();// 收款用户ID
                            double money = tppModel.getMoney();
                            if(lotteryType.equals(LotteryCashType.NORMAL+"")){
                                lotteryExchange(LotteryCashType.NORMAL,toUserId,money,autoDispatch);
                            }
                            else{
                                lotteryExchange(LotteryCashType.SCORE,toUserId,money,autoDispatch);
                            }
                        }
                        else if (TradeCode.C2006.equals(tradeCode)) {
                            // 根据订单号 查询代收Log
                            TppTradeLog tppTradeLog = tppTradeLogDao.find(tppModel.getOrderId());
                            tppTradeLog.setAutoDispatch(autoDispatch);
                            try {
                                TppTradeLog newTppTradeLog = lotteryPayService.createOrder(tppTradeLog);
                                ReturnResult returnResult = lotteryPayService.requestOrder(newTppTradeLog);
                                if (returnResult.isError()) {
                                    com.qdlc.p2p.common.util.MailUtil.sendMail("抽奖 - 兑现红包 - 代付提交成功 - 兑换失败", "抽奖兑现失败", returnResult.getErrorInfo());
                                }
                            } catch (Exception ex) {
                                com.qdlc.p2p.common.util.MailUtil.sendMail("抽奖 - 兑现红包 - 代付提交成功 - 兑换失败", "抽奖兑现失败", "");
                            }
                        }
                    }
                    //还款
                    else if (TppModel.DOREPAY.equals(tppModel.getServiceType())) {
                    	// 还款代收本息失败回滚还款状态重新还款，不需要保存调度任务
                    	// 还款代收加息
                    	if (TradeCode.C1005.toString().equals(tppModel.getTradeType())) {
                    		// 还款信息
                            BorrowRepayment borrowRepayment = borrowRepaymentService.findById(Long.valueOf(tppModel.getExtended()));

                            // 创建加息订单
                            TppTradeLog upRateTppTradeLog = borrowRepayUpRateCollectService.createOrder(borrowRepayment,autoDispatch);
                            // 执行加息订单
                            borrowRepayUpRateCollectService.requestOrder(upRateTppTradeLog);

                        // 代付还款金(本金+利息)
                    	} else if (TradeCode.C2004.toString().equals(tppModel.getTradeType())) {
                    		// 根据订单号 查询代付Log
                            TppTradeLog tppTradeLog = tppTradeLogDao.find(tppModel.getOrderId());
                            tppTradeLog.setAutoDispatch(autoDispatch);
                            TppTradeLog newTppTradeLog = borrowRepayPayService.createOrder(tppTradeLog);
                            borrowRepayPayService.requestOrder(newTppTradeLog);
                            // 代付加息金(加息)
                    	} else if (TradeCode.C2005.toString().equals(tppModel.getTradeType())) {
                    		// 根据订单号 查询代付Log
                	        TppTradeLog tppTradeLog = tppTradeLogDao.find(tppModel.getOrderId());
                	        tppTradeLog.setAutoDispatch(autoDispatch);
                	        // 创建代付还款金(加息)订单
                            TppTradeLog newTppTradeLog = borrowRepayUpRatePayService.createOrder(tppTradeLog);
                            borrowRepayUpRatePayService.requestOrder(newTppTradeLog);
                    	}
                    }
                    // 更新触发状态为已处理
                	tppModel.setStatus(TppModel.STATUS_SUCEESS);
                    tppModel.setRespDesc(tppModel.getRespDesc() + desc +"→重新触发成功");
                } catch (Exception e) {
                    isSuccess = false;
                    tppModel.setStatus(TppModel.STATUS_FAIL);
                    tppModel.setRespDesc(e.getMessage());
                    logger.info(e.getMessage());
                }
            } else {
            	if (StringUtil.isBlank(tpp)) {
            		logger.info("该调度任务未生成！");
            	} else {
            		logger.info("该调度任务已被处理过！订单号:" + tpp.getOrderId());            		
            	}
            }
            try {
                // 更新操作日志
                tppDao.update(tppModel.prototype());
            } catch (Exception e) {
                logger.error(e + "更新交易日志出错！！！");
            }
        }
    }


    private InterestCalculator experienceInterestCalculator(BorrowModel borrowModel, Date tenderAddTime) {
        double apr = borrowModel.getApr() / 100;
        InterestCalculator ic = new OnetimeRepaymentCalculator(borrowModel.getMoney(), apr, tenderAddTime, 1, 0);
        if (borrowModel.getBorrowTimeType() == BorrowTimeType.DAY) {
            ic.calculator(borrowModel.getTimeLimit());
        } else {
            ic.calculator();
        }
        return ic;
    }

    public InterestCalculator interestCalculator(Borrow borrow, double validAccount) {

        boolean flag = (borrow.getStatus() == BorrowStatus.STATUS_PUBLISHING)
                || (borrow.getStatus() == BorrowStatus.STATUS_RECHECK_PASS)
                || (borrow.getIsTender() == 1);

        double apr = borrow.getApr() / 100;
        Date date;
        VerifyLog verifyLog;
        if (flag) {
            verifyLog = verifyLogDao.findByType(borrow.getId(), "borrow", 2); // 2:复审
        } else {
            verifyLog = verifyLogDao.findByType(borrow.getId(), "borrow", 1); // 1:初审
        }
        if (verifyLog != null && verifyLog.getTime() != null) {
            date = verifyLog.getTime();
        } else {
            date = DateUtil.getNow();
        }

        // 利息管理费
        double manageFee = 0;
        // 期数
        int periods = borrow.getTimeLimit();
        // 利息实例
        InterestCalculator calculator;
        switch (borrow.getStyle()) {
            case BorrowStyle.STYLE_ONETIME_REPAYMENT: // ,一次性还款
                if (borrow.getBorrowTimeType() == BorrowTimeType.DAY) { // 天标
                    periods = 1;
                }
                calculator = new OnetimeRepaymentCalculator(validAccount, apr, date, periods, manageFee);
                if (borrow.getBorrowTimeType() == BorrowTimeType.DAY) { // 天标
                    calculator.calculator(borrow.getTimeLimit());
                } else {
                    calculator.calculator();
                }
                break;
            case BorrowStyle.STYLE_MONTHLY_INTEREST:// 每月还息到期还本
                calculator = new MonthlyInterestCalculator(validAccount, apr, date, periods, flag, manageFee);
                calculator.calculator();
                break;
            case BorrowStyle.STYLE_INSTALLMENT_REPAYMENT:// 等额本息
                calculator = new InstallmentRepaymentCalculator(validAccount, apr, date, periods, manageFee);
                calculator.calculator();
                break;
            default:
                throw new BusinessException("还款类型不正确!无法投标");
        }
        return calculator;
    }

    public List<BorrowCollection> experienceCreateCollectionList(BorrowTender borrowTender, InterestCalculator ic, Borrow borrow) {
        List<BorrowCollection> collectList = new ArrayList<BorrowCollection>();
        List<EachPlan> eachPlanList = ic.getEachPlanList();
        // 拼装Collection对象 批量插入还款表
        int i = 0;
        double totalInterest = 0; //利息总和
        double totalCapital = 0; //本金总和

        BorrowCollection borrowCollection;
        for (EachPlan eachPlan : eachPlanList) {
            borrowCollection = new BorrowCollection();
            borrowCollection.setBorrow(borrow); // 标
            borrowCollection.setTender(borrowTender); // 投标
            borrowCollection.setUser(borrowTender.getUser());// 投标用户

            borrowCollection.setInterest(eachPlan.getInterest()); // 利息
            borrowCollection.setCapital(eachPlan.getCapital());// 本金
            borrowCollection.setRepaymentAccount(eachPlan.getTotal()); // 预还金额
            borrowCollection.setStatus(BorrowCollectionStatus.NO_REPAYMENT); // 未还款
            borrowCollection.setRepaymentYesAccount(0.00);// 已还金额
            borrowCollection.setLateDays(0); // 逾期天数
            borrowCollection.setLateInterest(0.00); // 逾期利息

            double borrowFee = SystemConfigHelper.getDoubleValue(SystemConfigHelper.Nid.INVESTOR_MANAGE_FEE);
            borrowFee = BigDecimalUtil.mul(borrowCollection.getInterest(), BigDecimalUtil.div(borrowFee, 100));
            borrowFee = BigDecimalUtil.round(borrowFee); // 四舍五入
            borrowCollection.setManageFee(borrowFee); // 管理费
            borrowCollection.setAddIp(Global.getIP()); // IP地址
            borrowCollection.setAddTime(DateUtil.getNow()); // 时间

            if (i == eachPlanList.size() - 1) { // 最后一期做减法(利息做减法，本金做减法，生成最后一期的待收本金，待收利息，)
                double interest = borrowTender.getInterest();
                //计算最后一期利息
                double different = BigDecimalUtil.sub(interest, totalInterest);
                borrowCollection.setInterest(different); // 利息
                //计算最后一期本金
                double differentCapital = BigDecimalUtil.sub(borrowTender.getAccount(), totalCapital);
                borrowCollection.setCapital(differentCapital); // 本金
                borrowCollection.setRepaymentAccount(BigDecimalUtil.add(different)); // 归还金额
            }
            totalInterest = BigDecimalUtil.add(totalInterest, eachPlan.getInterest());
            totalCapital = BigDecimalUtil.add(totalCapital, eachPlan.getCapital());
            borrowCollection.setPeriod(i++);

            // 体验标还款时间 = 投标时间 + 借款期限
            if (borrow.getCategory() == BorrowCategory.EXPERIENCE) {
                borrowCollection.setRepaymentTime(DateUtil.rollDay(borrowTender.getAddTime(), borrow.getTimeLimit())); // 还款时间
            }

            collectList.add(borrowCollection);
        }
        borrowCollectionDao.save(collectList); // 生成 所有每期的归还计划表
        return collectList;
    }


    public void handleExTenderAfterFullSuccess(BorrowTender tender) {

        BorrowTenderDao tenderDao = (BorrowTenderDao) BeanUtil.getBean("borrowTenderDao");
        User tenderUser = tender.getUser();

        // 生成待收利息
        double interest = tender.getInterest(); // 利息
        Global.setTransfer("money", interest);
        Global.setTransfer("tender", tender);
        AbstractExecuter waitExecuter = ExecuterHelper.getExecuter(BorrowExWaitInterestExecuter.class);

        Borrow borrow = tender.getBorrow();
        BorrowModel model = BorrowModel.instance(borrow);
        waitExecuter.execute(interest, tenderUser, new User(1));

        // 修改Tender表中的待收利息
        tender.setWaitAccount(tender.getRepaymentAccount());
        tender.setWaitInterest(tender.getInterest());
        // 体验标还款时间 = 投标时间 + 借款期限
        Date exprepaymentTime = DateUtil.rollDay(tender.getAddTime(), model.getTimeLimit());
        tender.setRepaymentTime(exprepaymentTime);
        tenderDao.update(tender);
    }

    private void redEnvelopeExchange(long[] redEnvelopeIds, long exchangeUserId, byte redEnvelopeType,String useType, int autoDispatch) {
        try {
            TppTradeLog tppTradeLog = redEnvelopeCollectService.createOrder(redEnvelopeIds, exchangeUserId, redEnvelopeType, useType,autoDispatch);
            ReturnResult returnResult = redEnvelopeCollectService.requestOrder(tppTradeLog);
            if (returnResult.isError()) {
                // do nothing
                com.qdlc.p2p.common.util.MailUtil.sendMail("投标 - 兑现红包 - 代收提交成功 - 兑换失败", "红包兑现失败", returnResult.getErrorInfo());
            }
        } catch (Exception ex) {
            com.qdlc.p2p.common.util.MailUtil.sendMail("投标 - 兑现红包 - 代收提交成功 - 兑换失败", "红包兑现失败", "");
        }
    }

    private void lotteryExchange(byte lotteryType, long userId, double money,int autoDispatch) {
        try {
            TppTradeLog tppTradeLog = lotteryCollectService.createOrder(lotteryType,userId,money,autoDispatch);
            ReturnResult returnResult = lotteryCollectService.requestOrder(tppTradeLog);
            if (returnResult.isError()) {
                // do nothing
                com.qdlc.p2p.common.util.MailUtil.sendMail("抽奖 - 兑现现金 - 代收提交成功 - 兑换失败", "抽奖兑现失败", returnResult.getErrorInfo());
            }
        } catch (Exception ex) {
            com.qdlc.p2p.common.util.MailUtil.sendMail("抽奖 - 兑现红包 - 代收提交成功 - 兑换失败", "抽奖兑现失败", "");
        }
    }
}
